﻿using System;
using SlamCms.Caching;
using SlamCms.Common;
using SlamCms.Services;
using System.Linq;

namespace SlamCms.Data
{
	public class DataContextCache
	{
		private readonly SlamCmsConfiguration _configuration;

		internal DataContextCache(SlamCmsConfiguration configuration)
		{
			this._configuration = configuration;
		}

		private ICacheManager GetCacheManager()
		{
			return _configuration.Services.GetService<ICacheManager>();
		}

		public bool Contains(string key, bool allowDirty = true)
		{
			var cacheManager = GetCacheManager();
			if (cacheManager == null)
				return false;

			return cacheManager.Contains("SLAMCMS_{0}".F(key), allowDirty);
		}

		public T Get<T>(string key, bool allowDirty = true) where T : class
		{
			var cacheManager = GetCacheManager();
			if (cacheManager == null)
				return (T)null;

			return cacheManager.Get<T>("SLAMCMS_{0}".F(key), allowDirty);
		}

		public void Save<T>(string key, T instance, TimeSpan? timeout = null, bool sliding = false) where T : class
		{
			var cacheManager = GetCacheManager();
			if (cacheManager == null)
				return;

			cacheManager.Save("SLAMCMS_{0}".F(key), instance, timeout, sliding);
		}

		public void Invalidate(string key)
		{
			var cacheManager = GetCacheManager();
			if (cacheManager == null)
				return;

			cacheManager.Remove("SLAMCMS_{0}".F(key));
		}

		public void InvalidateTags()
		{
			Invalidate(Constants.Cache.TagTree);
			Invalidate(Constants.Cache.Tag);
			Invalidate(Constants.Cache.TagCategory);
			Invalidate(Constants.Cache.TagCulture);
			Invalidate(Constants.Cache.TagCategoryCulture);
			Invalidate(Constants.Cache.DefaultTag);
			Invalidate(Constants.Cache.ContentTypeTag);
		}

		public void InvalidateUsers()
		{
			Invalidate(Constants.Cache.User);
			Invalidate(Constants.Cache.Group);
		}

		public void InvalidateCore()
		{
			Invalidate(Constants.Cache.SiteOrListDefault);
			Invalidate(Constants.Cache.ContentType);
			Invalidate(Constants.Cache.Status);
			Invalidate(Constants.Cache.List);
			Invalidate(Constants.Cache.Site);
			Invalidate(Constants.Cache.SiteCollection);
			Invalidate(Constants.Cache.Zone);
			Invalidate(Constants.Cache.FeatureLocation);
		}

		public void InvalidateSitemaps()
		{
			InvalidateKeys("SLAMCMS_{0}".F(Constants.Cache.Sitemap));
		}

		public void InvalidateQueries()
		{
			InvalidateKeys("SLAMCMS_{0}".F(Constants.Cache.Query));
		}

		public void InvalidateKeys(string startingWith)
		{
			var cacheManager = GetCacheManager();
			var keys = cacheManager.Keys.Where(x => x.StartsWith(startingWith, StringComparison.InvariantCultureIgnoreCase));

			foreach (var key in keys)
			{
				cacheManager.Remove(key);
			}
		}
	}
}
